package com.medical.literature.recognition.service.impl;

import com.medical.literature.common.exception.BusinessException;
import com.medical.literature.recognition.dto.RecognitionRequest;
import com.medical.literature.recognition.dto.RecognitionResult;
import com.medical.literature.recognition.service.DocumentParseService;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.tika.Tika;
import org.apache.tika.exception.TikaException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 文档解析服务实现类
 */
@Service
public class DocumentParseServiceImpl implements DocumentParseService {
    
    // 手动添加log变量
    private static final Logger log = LoggerFactory.getLogger(DocumentParseServiceImpl.class);
    
    @Value("${recognition.file.base-path:D:/upload/literature/}")
    private String basePath;
    
    private final Tika tika = new Tika();
    private final ITesseract tesseract;
    
    public DocumentParseServiceImpl() {
        // 初始化Tesseract OCR
        tesseract = new Tesseract();
        // 设置训练数据路径（需要下载中文训练数据）
        // tesseract.setDatapath("path/to/tessdata");
        tesseract.setLanguage("chi_sim+eng"); // 中文简体+英文
    }

    @Override
    public RecognitionResult parseDocument(RecognitionRequest request) {
        RecognitionResult result = new RecognitionResult();
        result.setLiteratureId(request.getLiteratureId());
        
        try {
            log.info("开始文档解析，请求参数: {}", request);
            String textContent = extractText(request.getFilePath(), request.getFileType());
            result.setTextContent(textContent);
            result.setConfidence(0.95); // 模拟置信度
            result.setStatus(2); // 已完成
            
            log.info("文档解析成功: {}", request.getFilePath());
        } catch (Exception e) {
            log.error("文档解析失败: {}", e.getMessage(), e);
            result.setStatus(3); // 失败
            result.setErrorMessage(e.getMessage());
        }
        
        return result;
    }

    @Override
    public String extractText(String filePath, String fileType) {
        try {
            log.info("开始提取文本，文件路径: {}, 文件类型: {}", filePath, fileType);
            // 构造完整文件路径
            String fullFilePath = getFullFilePath(filePath);
            log.info("构造完整文件路径: {}", fullFilePath);
            File file = new File(fullFilePath);
            if (!file.exists()) {
                log.error("文件不存在: {}", fullFilePath);
                throw new BusinessException("文件不存在: " + fullFilePath);
            }
            
            log.info("文件存在，开始提取文本");
            if (fileType != null && fileType.toLowerCase().contains("pdf")) {
                log.info("使用PDF提取方式");
                return extractTextFromPDF(file);
            } else {
                log.info("使用Tika提取方式");
                return extractTextWithTika(file);
            }
        } catch (Exception e) {
            log.error("文本提取失败: {}", e.getMessage(), e);
            throw new BusinessException("文本提取失败: " + e.getMessage());
        }
    }

    @Override
    public String recognizeImageText(String imagePath) {
        try {
            log.info("开始OCR识别，图片路径: {}", imagePath);
            // 构造完整文件路径
            String fullImagePath = getFullFilePath(imagePath);
            File imageFile = new File(fullImagePath);
            if (!imageFile.exists()) {
                log.error("图片文件不存在: {}", fullImagePath);
                throw new BusinessException("图片文件不存在: " + fullImagePath);
            }
            
            String result = tesseract.doOCR(imageFile);
            log.info("OCR识别完成: {}", fullImagePath);
            return result;
        } catch (TesseractException e) {
            log.error("OCR识别失败: {}", e.getMessage(), e);
            throw new BusinessException("OCR识别失败: " + e.getMessage());
        }
    }
    
    /**
     * 构造完整文件路径
     * @param relativePath 相对路径
     * @return 完整文件路径
     */
    private String getFullFilePath(String relativePath) {
        if (!StringUtils.hasText(relativePath)) {
            throw new BusinessException("文件路径不能为空");
        }
        
        // 确保基础路径以分隔符结尾
        String normalizedBasePath = basePath;
        if (normalizedBasePath != null) {
            normalizedBasePath = normalizedBasePath.replace("\\", "/").replaceAll("/+$", "");
            if (!normalizedBasePath.endsWith("/")) {
                normalizedBasePath += "/";
            }
        }
        
        // 如果basePath为null，使用默认路径
        if (normalizedBasePath == null) {
            normalizedBasePath = "D:/upload/literature/";
        }
        
        // 处理相对路径，确保使用正斜杠
        String normalizedRelativePath = relativePath.replace("\\", "/");
        
        // 构造完整路径，使用Paths.get确保跨平台兼容性
        Path basePathObj = Paths.get(normalizedBasePath);
        Path fullPathObj = basePathObj.resolve(normalizedRelativePath);
        String fullPath = fullPathObj.toString();
        
        log.info("构造完整文件路径: 基础路径={}, 相对路径={}, 完整路径={}", normalizedBasePath, normalizedRelativePath, fullPath);
        return fullPath;
    }
    
    /**
     * 使用PDFBox提取PDF文本
     */
    private String extractTextFromPDF(File file) throws IOException {
        log.info("开始使用PDFBox提取文本，文件: {}", file.getAbsolutePath());
        try (PDDocument document = PDDocument.load(file)) {
            PDFTextStripper pdfStripper = new PDFTextStripper();
            String text = pdfStripper.getText(document);
            log.info("PDF文本提取完成，文本长度: {}", text.length());
            return text;
        } catch (IOException e) {
            log.error("PDF文本提取失败: {}", e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 使用Tika提取文本
     */
    private String extractTextWithTika(File file) throws IOException, TikaException {
        log.info("开始使用Tika提取文本，文件: {}", file.getAbsolutePath());
        try (FileInputStream fis = new FileInputStream(file)) {
            String text = tika.parseToString(fis);
            log.info("Tika文本提取完成，文本长度: {}", text.length());
            return text;
        } catch (IOException | TikaException e) {
            log.error("Tika文本提取失败: {}", e.getMessage(), e);
            throw e;
        }
    }
}